home *** CD-ROM | disk | FTP | other *** search
/ MacTech 1 to 12 / MacTech-vol-1-12.toast / Source / MacTech® Magazine / Volume 09 - 1993 / 09.04 Apr 93 / Creating EPSF Files / PSDGeomProcs.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-07-15  |  8.4 KB  |  321 lines  |  [TEXT/KAHL]

  1. /* PSDGeomProcs.c */
  2. /* Here are the Quickdraw plug-in procs which handle the comparatively
  3.    simple geometric stuff */
  4. /* Copyright 1992, Gary D. McGath */
  5.  
  6. #include "psd.h"
  7.  
  8. extern int thePSFile;            /* ID of file to output to */
  9.  
  10.  
  11. pascal void psdRectProc(GrafVerb verb, Rect *theRect);
  12. pascal psdOvalProc(GrafVerb verb, Rect *theRect);
  13. pascal psdrRectProc(GrafVerb verb, Rect *theRect, short ovalwidth, short ovalheight);
  14. pascal psdLineProc(Point newPt);
  15. pascal psdPolyProc(GrafVerb verb, PolyHandle thePoly);
  16. pascal psdArcProc(GrafVerb verb, Rect *theRect, short startAngle, short arcAngle);
  17. void psdDrawLine(Point oldPt, Point newPt);
  18. void psdWriteRect(Rect *theRect);
  19. void psdDrawLine(Point oldPt, Point newPt);
  20.  
  21.  
  22.  
  23. /* psdRectProc -- one of the easiest (ha!) */
  24. /* Should support non-square pen size at least for lines and rectangles */
  25. pascal void psdRectProc(GrafVerb verb, Rect *theRect)
  26. {
  27.     /* First need to check for state changes and output needed code */
  28.     if (thePort->pnVis < 0)
  29.         return;                        /* nothing to draw */
  30.  
  31.     switch(verb) {
  32.     case frame:
  33.  
  34.         if (thePort->pnSize.h == 0 && thePort->pnSize.v == 0)
  35.             return;
  36.         psdSetPenPat();            /* update gray level to pen pattern */
  37.         psdWriteRect(theRect);
  38.         OutputNum(thePort->pnSize.h,thePSFile);    /* thickness of vertical strokes */
  39.         OutputNum(thePort->pnSize.v,thePSFile);    /* thickness of horizontal strokes */
  40.         OutputString("frrec\r",thePSFile);
  41.         break;
  42.  
  43.     case fill:
  44.     case paint:                /* to paint is to fill with the paint color & pattern */
  45.     case erase:                /* like paint, but background color & no pattern */
  46.  
  47.         if (verb == paint)
  48.             psdSetPenPat();            /* update gray level to pen pattern */
  49.         else if (verb == erase)
  50.             OutputGray(0);
  51.         else psdSetFillPat();        /* or fill pattern, if doing fill */
  52.         psdWriteRect(theRect);
  53.         OutputString("flrec\r",thePSFile);
  54.         break;
  55.  
  56.     case invert:
  57.         break;                    /* invert isn't supported */
  58.  
  59.     }
  60. }
  61.  
  62. /* psdOvalProc -- draw an oval.  PostScript knows about circles but not
  63.    ellipses, so we have to scale the circular path (but *not* the stroking
  64.    of it) to an ellipse.  For the present, we assume that the pen is square
  65.    (equal in horizontal and vertical dimensions). */
  66. pascal psdOvalProc(GrafVerb verb, Rect *theRect)
  67. {
  68.     if (thePort->pnVis < 0)
  69.         return;                        /* nothing to draw */
  70.  
  71.     switch(verb) {
  72.     case frame:
  73.  
  74.         if (thePort->pnSize.h == 0 && thePort->pnSize.v == 0)
  75.             return;
  76.         psdSetPenPat();            /* update gray level to pen pattern */
  77.         psdWriteRect(theRect);
  78.         OutputNum(thePort->pnSize.h,thePSFile);    /* thickness of vertical strokes */
  79.         OutputString("froval\r",thePSFile);
  80.         break;
  81.     
  82.     case fill:
  83.     case paint:
  84.     case erase:
  85.         
  86.         if (verb == paint)
  87.             psdSetPenPat();            /* update gray level to pen pattern */
  88.         else if (verb == erase)
  89.             OutputGray(0);
  90.         else psdSetFillPat();        /* or fill pattern, if doing fill */
  91.         psdWriteRect(theRect);
  92.         OutputString("floval\r",thePSFile);
  93.         break;
  94.  
  95.     case invert:
  96.         break;                        /* invert isn't supported */
  97.     }
  98. }
  99.  
  100.  
  101. /* psdRRectProc -- draw a round-cornered rectangle. In this case, we make
  102.    two simplifying assumptions: that the pen is square and that the corners
  103.    are circular (width = height). */
  104. pascal psdrRectProc(GrafVerb verb, Rect *theRect, short ovalwidth, 
  105.                 short ovalheight)
  106. {
  107.     if (thePort->pnVis < 0)
  108.         return;                        /* nothing to draw */
  109.  
  110.     switch(verb) {
  111.     case frame:
  112.  
  113.         psdSetPenPat();            /* update gray level to pen pattern */
  114.         psdWriteRect(theRect);
  115.         OutputNum(thePort->pnSize.h,thePSFile);    /* thickness of vertical strokes */
  116.         OutputDouble(ovalwidth/2.0,thePSFile);    /* oval radius */
  117.         OutputString("frrrect\r",thePSFile);
  118.         break;
  119.     
  120.     case fill:
  121.     case paint:
  122.     case erase:
  123.         
  124.         if (verb == paint)
  125.             psdSetPenPat();            /* update gray level to pen pattern */
  126.         else if (verb == erase)
  127.             OutputGray(0);
  128.         else psdSetFillPat();        /* or fill pattern, if doing fill */
  129.         psdWriteRect(theRect);
  130.         OutputDouble(ovalwidth/2.0,thePSFile);    /* oval radius */
  131.         OutputString("flrrect\r",thePSFile);
  132.         break;
  133.  
  134.     case invert:
  135.         break;                        /* invert isn't supported */
  136.     }
  137.  
  138. }
  139.  
  140.  
  141. /* psdLineProc -- draw a line from the current point to the new point.
  142.    "Lines" in Quickdraw are actually funny-shaped polygons. */
  143. pascal psdLineProc(Point newPt)
  144. {
  145.     Point oldPt;
  146.     oldPt = thePort->pnLoc;
  147.     thePort->pnLoc = newPt;
  148.     if (thePort->pnVis < 0 || (thePort->pnSize.h == 0 && thePort->pnSize.v == 0)) {
  149.         return;                        /* nothing to draw */
  150.     }
  151.     psdSetPenPat();            /* update gray level to pen pattern */
  152.     psdDrawLine(oldPt, newPt);
  153. }
  154.  
  155.  
  156.  
  157. pascal psdPolyProc(GrafVerb verb, PolyHandle thePoly)
  158. {
  159.     int npoints;
  160.     register int i;
  161.     PolyPtr thePolyp;
  162.     Point prevPoint;
  163.     
  164.     HLock(thePoly);
  165.     thePolyp = *thePoly;
  166.     npoints = (thePolyp->polySize - 10) / 4;
  167.     switch(verb) {
  168.     case frame:
  169.         if (thePort->pnSize.h == 0 && thePort->pnSize.v == 0)
  170.             return;
  171.         psdSetPenPat();    
  172.         prevPoint = thePolyp->polyPoints[0];
  173.         for (i = 1; i < npoints; i++) {
  174.             psdDrawLine(prevPoint,thePolyp->polyPoints[i]);
  175.             prevPoint = thePolyp->polyPoints[i];
  176.         }
  177.         break;
  178.  
  179.     case fill:
  180.     case paint:
  181.     case erase:
  182.         if (verb == fill)
  183.             psdSetFillPat();
  184.         else if (verb == erase)
  185.             OutputGray(0);
  186.         else psdSetPenPat();
  187.         prevPoint = thePolyp->polyPoints[0];
  188.         OutputNum(prevPoint.h, thePSFile);
  189.         OutputNum(prevPoint.v, thePSFile);
  190.         OutputString("moveto ", thePSFile);
  191.         for (i = 1; i < npoints; i++) {
  192.             prevPoint = thePolyp->polyPoints[i];
  193.             OutputNum(prevPoint.h, thePSFile);
  194.             OutputNum(prevPoint.v, thePSFile);
  195.             OutputString("lineto ", thePSFile);
  196.         }
  197.         OutputString("closepath fill\r", thePSFile);
  198.         break;
  199.     case invert:
  200.         break;                        /* invert isn't supported */
  201.             
  202.     }
  203.     HUnlock(thePoly);
  204. }
  205.  
  206. pascal psdArcProc(GrafVerb verb, Rect *theRect, short startAngle, short arcAngle)
  207. {
  208.     if (thePort->pnVis < 0)
  209.         return;                        /* nothing to draw */
  210.  
  211.     if (arcAngle < 0) {                /* make angle always positive */
  212.         startAngle += arcAngle;
  213.         arcAngle = -arcAngle;
  214.     }
  215.     switch(verb) {
  216.     case frame:
  217.  
  218.         if (thePort->pnSize.h == 0 && thePort->pnSize.v == 0)
  219.             return;
  220.         psdSetPenPat();            /* update gray level to pen pattern */
  221.         psdWriteRect(theRect);
  222.         OutputNum(thePort->pnSize.h,thePSFile);    /* thickness of vertical strokes */
  223.         OutputNum(startAngle,thePSFile);
  224.         OutputNum(arcAngle,thePSFile);
  225.         OutputString("frarc\r",thePSFile);
  226.         break;
  227.     
  228.     case fill:
  229.     case paint:
  230.     case erase:
  231.         
  232.         if (verb == paint)
  233.             psdSetPenPat();            /* update gray level to pen pattern */
  234.         else if (verb == erase)
  235.             OutputGray(0);
  236.         else psdSetFillPat();        /* or fill pattern, if doing fill */
  237.         psdWriteRect(theRect);
  238.         OutputDouble(startAngle,thePSFile);
  239.         OutputDouble(arcAngle,thePSFile);
  240.         OutputString("flarc\r",thePSFile);
  241.         break;
  242.  
  243.     case invert:
  244.         break;                        /* invert isn't supported */
  245.     }
  246.  
  247.  
  248. }
  249.  
  250.  
  251. /* psdWriteRect -- output the coordinates of a rectangle. */
  252. void psdWriteRect(Rect *theRect)
  253. {
  254.     OutputNum(theRect->left,thePSFile);
  255.     OutputNum(theRect->top,thePSFile);
  256.     OutputNum(theRect->right,thePSFile);
  257.     OutputNum(theRect->bottom,thePSFile);
  258. }
  259.  
  260. /* This subroutine is used for both lines and polygons */
  261. void psdDrawLine(Point oldPt, Point newPt)
  262. {
  263.     int hdelta, vdelta;
  264.     Point startcorner, endcorner;
  265.     
  266.     /* horizontal and vertical lines should really be special-cased
  267.        for efficiency, but the general case works. */
  268.     if (newPt.h > oldPt.h) {
  269.         hdelta = thePort->pnSize.h;
  270.         startcorner.h = oldPt.h;
  271.         endcorner.h = newPt.h + hdelta;
  272.         if (newPt.v > oldPt.v) {
  273.             vdelta = thePort->pnSize.v;
  274.             startcorner.v = oldPt.v;
  275.             endcorner.v = newPt.v + vdelta;
  276.         }
  277.         else {                    /* newPt.v <= oldPt.v */
  278.             vdelta = -thePort->pnSize.v;
  279.             startcorner.v = oldPt.v - vdelta;
  280.             endcorner.v = newPt.v;
  281.         }
  282.     }
  283.     else {                        /* newPt.h <= oldPt.h */
  284.         hdelta = -thePort->pnSize.h;
  285.         startcorner.h = oldPt.h - hdelta;
  286.         endcorner.h = newPt.h;
  287.         if (newPt.v > oldPt.v) {
  288.             vdelta = thePort->pnSize.v;
  289.             startcorner.v = oldPt.v;
  290.             endcorner.v = newPt.v + vdelta;
  291.         }
  292.         else {                    /* newPt.v <= oldPt.v */
  293.             hdelta = -thePort->pnSize.h;
  294.             vdelta = -thePort->pnSize.v;
  295.             startcorner.v = oldPt.v - vdelta;
  296.             endcorner.v = newPt.v;
  297.         }
  298.     }
  299.     OutputNum(startcorner.h,thePSFile);
  300.     OutputNum(startcorner.v,thePSFile);
  301.     OutputString("moveto ",thePSFile);
  302.     OutputNum(hdelta,thePSFile);
  303.     OutputNum(0,thePSFile);
  304.     OutputString("rlineto ",thePSFile);
  305.     OutputNum(endcorner.h,thePSFile);
  306.     OutputNum(endcorner.v - vdelta,thePSFile);
  307.     OutputString("lineto ",thePSFile);
  308.     OutputNum(0,thePSFile);
  309.     OutputNum(vdelta,thePSFile);
  310.     OutputString("rlineto ",thePSFile);
  311.     OutputNum(-hdelta,thePSFile);
  312.     OutputNum(0,thePSFile);
  313.     OutputString("rlineto ",thePSFile);
  314.     OutputNum(startcorner.h,thePSFile);
  315.     OutputNum(startcorner.v+vdelta,thePSFile);
  316.     OutputString("lineto closepath fill\r",thePSFile);
  317. }
  318.  
  319.  
  320.  
  321.